package org.onosproject.ngsdn.tutorial;

import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.criteria.PiCriterion;
import org.onosproject.net.pi.model.PiActionId;
import org.onosproject.net.pi.model.PiActionParamId;
import org.onosproject.net.pi.model.PiMatchFieldId;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.ngsdn.tutorial.common.Utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Random;

import static org.onosproject.ngsdn.tutorial.RouterComponent.*;

public class ModalComponent {
    private static final Logger log = LoggerFactory.getLogger(ModalComponent.class);

    private static ApplicationId appId = MainComponent.getAppId();

    /******************IP转MF模态和MF转IP模态流表**************************************/
    public static FlowRule buildMFForwardRule(DeviceId deviceId, Long dstGuid, long port) {
        //log.info("******Build MF Forward Flow Rule********");

        final String tableId = "IngressPipeImpl.mf_forward_table";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.mf.dest_guid"), dstGuid)
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.set_egress_port"))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);
        //log.info("******MF Forward Flow Rule Done!********");

        return rule;
    }
    public static FlowRule buildAnyModelForwardRule(DeviceId deviceId, String dstIP, long port, String modal) {
        //log.info("******Build MF Forward Flow Rule********");

        switch (modal) {
            case "MF":
                Long dstGuid = IpToMf.get(dstIP);
                final String mftableId = "IngressPipeImpl.mf_forward_table";
                final PiCriterion mfcriterion = PiCriterion.builder()
                        .matchExact(PiMatchFieldId.of("hdr.mf.dest_guid"), dstGuid)
                        .build();
                final PiAction mfaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.set_egress_port"))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule mfrule = Utils.buildFlowRule(deviceId, appId, mftableId, mfcriterion, mfaction);
                //log.info("******Build IP to MF table Done********");
                return mfrule;
            case "GEO":
                Long dstGeo = IpToGeo.get(dstIP);

                final String geotableId = "IngressPipeImpl.geo_forward_table";

                final PiCriterion geocriterion = PiCriterion.builder()
                        .matchExact(PiMatchFieldId.of("hdr.geo.dest_geo"), dstGeo)
                        .build();
                final PiAction geoaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.set_egress_port"))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule georule = Utils.buildFlowRule(deviceId, appId, geotableId, geocriterion, geoaction);
                //log.info("******Build IP to MF table Done********");

                return georule;
            case "NDN":
                Long dstNdn = IpToNdn.get(dstIP);

                final String ndntableId = "IngressPipeImpl.ndn_forward_table";

                final PiCriterion ndncriterion = PiCriterion.builder()
                        .matchExact(PiMatchFieldId.of("hdr.ndn.dest_ndn"), dstNdn)
                        .build();
                final PiAction ndnaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.set_egress_port"))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();


                final FlowRule ndnrule = Utils.buildFlowRule(deviceId, appId, ndntableId, ndncriterion, ndnaction);

                return ndnrule;
            default:
                log.warn("Not support modal");
                break;
        }

        //log.info("******Build IP to MF table Done********");

        return null;
    }
    public static FlowRule buildIP2AnyModelRule(DeviceId deviceId, String srcIP, String dstIP, long port, String modal) {
        //log.info("******Build IP to MF table*******");


        final String tableId = "IngressPipeImpl.ipv4_convers_table";
        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.ipv4.src_addr"), Ip4Address.valueOf(srcIP).toOctets())
                .matchExact(PiMatchFieldId.of("hdr.ipv4.dst_addr"), Ip4Address.valueOf(dstIP).toOctets())
                .build();
        switch (modal) {
            case "MF":
                Long srcGuid = IpToMf.get(srcIP);
                Long dstGuid = IpToMf.get(dstIP);
                final PiAction mfaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.ip_to_mf"))
                        .withParameter(new PiActionParam(PiActionParamId.of("src_guid"), srcGuid))
                        .withParameter(new PiActionParam(PiActionParamId.of("dest_guid"), dstGuid))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule mfrule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, mfaction);
                //log.info("******Build IP to MF table Done********");
                return mfrule;
            case "GEO":
                Long srcGeo = IpToGeo.get(srcIP);
                Long dstGeo = IpToGeo.get(dstIP);
                final PiAction geoaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.ip_to_geo"))
                        .withParameter(new PiActionParam(PiActionParamId.of("src_geo"), srcGeo))
                        .withParameter(new PiActionParam(PiActionParamId.of("dest_geo"), dstGeo))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule georule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, geoaction);
                //log.info("******Build IP to MF table Done********");

                return georule;
            case "NDN":
                Long srcNdn = IpToNdn.get(srcIP);
                Long dstNdn = IpToNdn.get(dstIP);

                final PiAction ndnaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.ip_to_ndn"))
                        .withParameter(new PiActionParam(PiActionParamId.of("src_ndn"), srcNdn))
                        .withParameter(new PiActionParam(PiActionParamId.of("dest_ndn"), dstNdn))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule ndnrule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, ndnaction);

                return ndnrule;
            default:
                log.warn("Not support modal");
                break;
        }

        //log.info("******Build IP to MF table Done********");

        return null;
    }
    public static FlowRule buildIP2MFRule(DeviceId deviceId, String srcIP, String dstIP, long port) {
        //log.info("******Build IP to MF table*******");

        Long srcGuid = IpToMf.get(srcIP);
        Long dstGuid = IpToMf.get(dstIP);
        final String tableId = "IngressPipeImpl.ipv4_convers_table";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.ipv4.src_addr"), Ip4Address.valueOf(srcIP).toOctets())
                .matchExact(PiMatchFieldId.of("hdr.ipv4.dst_addr"), Ip4Address.valueOf(dstIP).toOctets())
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.ip_to_mf"))
                .withParameter(new PiActionParam(PiActionParamId.of("src_guid"), srcGuid))
                .withParameter(new PiActionParam(PiActionParamId.of("dest_guid"), dstGuid))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .withParameter(new PiActionParam(PiActionParamId.of("spi_addr"), 0))
                .withParameter(new PiActionParam(PiActionParamId.of("first_head_offset"), 14))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_length"), 20))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_offset"), 14))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);
        //log.info("******Build IP to MF table Done********");

        return rule;
    }
    public static FlowRule buildAnyModel2IPRule(DeviceId deviceId, String srcIP, String dstIP, MacAddress targetMac, long port, String modal) {
        //log.info("******Build MF to IP table ********");

        switch (modal) {
            case "MF":
                Long srcGuid = IpToMf.get(srcIP);
                Long dstGuid = IpToMf.get(dstIP);
                final String mftableId = "IngressPipeImpl.mf_conversion_table";
                final PiCriterion mfcriterion = PiCriterion.builder()
                        .matchExact(PiMatchFieldId.of("hdr.mf.src_guid"), srcGuid)
                        .matchExact(PiMatchFieldId.of("hdr.mf.dest_guid"), dstGuid)
                        .build();
                final PiAction mfaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.mf_to_ip"))
                        .withParameter(new PiActionParam(PiActionParamId.of("target_mac"), targetMac.toBytes()))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule mfrule = Utils.buildFlowRule(deviceId, appId, mftableId, mfcriterion, mfaction);
                //log.info("******Build IP to MF table Done********");
                return mfrule;
            case "GEO":
                Long srcGeo = IpToGeo.get(srcIP);
                Long dstGeo = IpToGeo.get(dstIP);
                final String geotableId = "IngressPipeImpl.geo_conversion_table";

                final PiCriterion geocriterion = PiCriterion.builder()
                        .matchExact(PiMatchFieldId.of("hdr.geo.src_geo"), srcGeo)
                        .matchExact(PiMatchFieldId.of("hdr.geo.dest_geo"), dstGeo)
                        .build();
                final PiAction geoaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.geo_to_ip"))
                        .withParameter(new PiActionParam(PiActionParamId.of("target_mac"), targetMac.toBytes()))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule georule = Utils.buildFlowRule(deviceId, appId, geotableId, geocriterion, geoaction);
                //log.info("******Build IP to MF table Done********");

                return georule;
            case "NDN":
                Long srcNdn = IpToNdn.get(srcIP);
                Long dstNdn = IpToNdn.get(dstIP);
                final String ndntableId = "IngressPipeImpl.ndn_conversion_table";

                final PiCriterion ndncriterion = PiCriterion.builder()
                        .matchExact(PiMatchFieldId.of("hdr.ndn.src_ndn"), srcNdn)
                        .matchExact(PiMatchFieldId.of("hdr.ndn.dest_ndn"), dstNdn)
                        .build();
                final PiAction ndnaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.ndn_to_ip"))
                        .withParameter(new PiActionParam(PiActionParamId.of("target_mac"), targetMac.toBytes()))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule ndnrule = Utils.buildFlowRule(deviceId, appId, ndntableId, ndncriterion, ndnaction);

                return ndnrule;
            default:
                log.warn("Not support modal");
                break;
        }

        //log.info("******Build IP to MF table Done********");

        return null;
    }
    public static FlowRule buildMF2IPRule(DeviceId deviceId, Long srcGuid, Long dstGuid, MacAddress targetMac, long port) {
        //log.info("******Build MF to IP table ********");
        final String tableId = "IngressPipeImpl.mf_conversion_table";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.mf.src_guid"), srcGuid)
                .matchExact(PiMatchFieldId.of("hdr.mf.dest_guid"), dstGuid)
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.mf_to_ip"))
                .withParameter(new PiActionParam(PiActionParamId.of("target_mac"), targetMac.toBytes()))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);
        //log.info("******Build MF to IP table Done********");

        return rule;
    }

    /******************************IP转Geo模态和Geo转IP模态流表**************************************/
    public static FlowRule buildGeoForwardRule(DeviceId deviceId, long dest_geo, long port) {
        final String tableId = "IngressPipeImpl.geo_forward_table";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.geo.dest_geo"), dest_geo)
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.set_egress_port"))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);

        return rule;
    }

    public static FlowRule buildIP2GeoRule(DeviceId deviceId, String srcIP, String dstIP, long port) {
        final String tableId = "IngressPipeImpl.ipv4_convers_table";

        Long srcGeo = IpToGeo.get(srcIP);
        Long dstGeo = IpToGeo.get(dstIP);
        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.ipv4.src_addr"), Ip4Address.valueOf(srcIP).toOctets())
                .matchExact(PiMatchFieldId.of("hdr.ipv4.dst_addr"), Ip4Address.valueOf(dstIP).toOctets())
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.ip_to_geo"))
                .withParameter(new PiActionParam(PiActionParamId.of("src_geo"), srcGeo))
                .withParameter(new PiActionParam(PiActionParamId.of("dest_geo"), dstGeo))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .withParameter(new PiActionParam(PiActionParamId.of("spi_addr"), 0))
                .withParameter(new PiActionParam(PiActionParamId.of("first_head_offset"), 14))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_length"), 20))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_offset"), 14))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);

        return rule;
    }

    public static FlowRule buildGeo2IPRule(DeviceId deviceId, long src_geo, long dest_geo, MacAddress targetMac, long port) {
        final String tableId = "IngressPipeImpl.geo_conversion_table";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.geo.src_geo"), src_geo)
                .matchExact(PiMatchFieldId.of("hdr.geo.dest_geo"), dest_geo)
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.geo_to_ip"))
                .withParameter(new PiActionParam(PiActionParamId.of("target_mac"), targetMac.toBytes()))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);

        return rule;
    }
    /******************************IP转NDN模态和NDN转IP模态流表**************************************/
    public static FlowRule buildNdnForwardRule(DeviceId deviceId, long dest_ndn, long port) {
        final String tableId = "IngressPipeImpl.ndn_forward_table";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.ndn.dest_ndn"), dest_ndn)
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.set_egress_port"))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);

        return rule;
    }

    public static FlowRule buildIP2NdnRule(DeviceId deviceId, String srcIP, String dstIP, long port) {
        final String tableId = "IngressPipeImpl.ipv4_convers_table";

        Long srcNdn = IpToNdn.get(srcIP);
        Long dstNdn = IpToNdn.get(dstIP);
        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.ipv4.src_addr"), Ip4Address.valueOf(srcIP).toOctets())
                .matchExact(PiMatchFieldId.of("hdr.ipv4.dst_addr"), Ip4Address.valueOf(dstIP).toOctets())
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.ip_to_ndn"))
                .withParameter(new PiActionParam(PiActionParamId.of("src_ndn"), srcNdn))
                .withParameter(new PiActionParam(PiActionParamId.of("dest_ndn"), dstNdn))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .withParameter(new PiActionParam(PiActionParamId.of("spi_addr"), 0))
                .withParameter(new PiActionParam(PiActionParamId.of("first_head_offset"), 14))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_length"), 20))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_offset"), 14))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);

        return rule;
    }

    public static FlowRule buildNdn2IPRule(DeviceId deviceId, long src_ndn, long dest_ndn, MacAddress targetMac, long port) {
        final String tableId = "IngressPipeImpl.ndn_conversion_table";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.ndn.src_ndn"), src_ndn)
                .matchExact(PiMatchFieldId.of("hdr.ndn.dest_ndn"), dest_ndn)
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.ndn_to_ip"))
                .withParameter(new PiActionParam(PiActionParamId.of("target_mac"), targetMac.toBytes()))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);

        return rule;
    }
    /***********************************IP模态流表**************************************/
    public static FlowRule buildCoreIPForwardRule(DeviceId deviceId, String dstIP, long port) {
        //log.info("******Build IP Forward table ********");
        final String tableId = "IngressPipeImpl.ipv4_forward_table";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.ipv4.dst_addr"), Ip4Address.valueOf(dstIP).toOctets())
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.set_egress_port"))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);
        //log.info("******Build IP Forward table Done********");

        return rule;
    }

    public static FlowRule buildEdgeIPForwardRule(DeviceId deviceId, String dstIP, MacAddress targetMac, long port) {
        //log.info("******Build IP Forward table ********");
        final String tableId = "IngressPipeImpl.ipv4_forward_table";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.ipv4.dst_addr"), Ip4Address.valueOf(dstIP).toOctets())
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.set_egress_port_and_mac"))
                .withParameter(new PiActionParam(PiActionParamId.of("target_mac"), targetMac.toBytes()))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);
        //log.info("******Build IP Forward table Done********");

        return rule;
    }

    public static FlowRule buildPollingIPForwardRule(DeviceId deviceId, String srcIP, String dstIP) {
        //log.info("******Build IP Forward table ********");
        final String tableId = "IngressPipeImpl.ipv4_polling_table";
        Random numList = new Random();
        long num = numList.nextInt(1024);
        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("hdr.ipv4.src_addr"), Ip4Address.valueOf(srcIP).toOctets())
                .matchExact(PiMatchFieldId.of("hdr.ipv4.dst_addr"), Ip4Address.valueOf(dstIP).toOctets())
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.ipv4_static"))
                .withParameter(new PiActionParam(PiActionParamId.of("index"), num))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);
        //log.info("******Build IP Forward table Done********");

        return rule;
    }
    public static FlowRule buildStatefulForward2AnyModelRule(DeviceId deviceId, String srcIP, String dstIP, byte mod_result, long port, String modal) {
        //log.info("******Build IP Forward table ********");
        final String tableId = "IngressPipeImpl.stateful_forward";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("meta.mod_result"), mod_result)
                .build();
        switch (modal) {
            case "MF":
                Long srcGuid = IpToMf.get(srcIP);
                Long dstGuid = IpToMf.get(dstIP);
                final PiAction mfaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.ip_to_mf"))
                        .withParameter(new PiActionParam(PiActionParamId.of("src_guid"), srcGuid))
                        .withParameter(new PiActionParam(PiActionParamId.of("dest_guid"), dstGuid))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule mfrule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, mfaction);
                //log.info("******Build IP to MF table Done********");
                return mfrule;
            case "GEO":
                Long srcGeo = IpToGeo.get(srcIP);
                Long dstGeo = IpToGeo.get(dstIP);
                final PiAction geoaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.ip_to_geo"))
                        .withParameter(new PiActionParam(PiActionParamId.of("src_geo"), srcGeo))
                        .withParameter(new PiActionParam(PiActionParamId.of("dest_geo"), dstGeo))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule georule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, geoaction);
                //log.info("******Build IP to MF table Done********");

                return georule;
            case "NDN":
                Long srcNdn = IpToNdn.get(srcIP);
                Long dstNdn = IpToNdn.get(dstIP);

                final PiAction ndnaction = PiAction.builder()
                        .withId(PiActionId.of("IngressPipeImpl.ip_to_ndn"))
                        .withParameter(new PiActionParam(PiActionParamId.of("src_ndn"), srcNdn))
                        .withParameter(new PiActionParam(PiActionParamId.of("dest_ndn"), dstNdn))
                        .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                        .build();

                final FlowRule ndnrule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, ndnaction);

                return ndnrule;
            default:
                log.warn("Not support modal");
                break;
        }

        //log.info("******Build IP to MF table Done********");

        return null;
    }
    public static FlowRule buildStatefulForward2MFRule(DeviceId deviceId, String srcIP, String dstIP, byte mod_result,long port) {
        //log.info("******Build IP Forward table ********");
        Long srcGuid = IpToMf.get(srcIP);
        Long dstGuid = IpToMf.get(dstIP);
        final String tableId = "IngressPipeImpl.stateful_forward";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("meta.mod_result"), mod_result)
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.ip_to_mf"))
                .withParameter(new PiActionParam(PiActionParamId.of("src_guid"), srcGuid))
                .withParameter(new PiActionParam(PiActionParamId.of("dest_guid"), dstGuid))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .withParameter(new PiActionParam(PiActionParamId.of("spi_addr"), 0))
                .withParameter(new PiActionParam(PiActionParamId.of("first_head_offset"), 14))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_length"), 20))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_offset"), 14))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);
        //log.info("******Build IP Forward table Done********");

        return rule;
    }

    public static FlowRule buildStatefulForward2GeoRule(DeviceId deviceId, String srcIP, String dstIP, byte mod_result, long port) {
        //log.info("******Build IP Forward table ********");
        Long srcGeo = IpToGeo.get(srcIP);
        Long dstGeo = IpToGeo.get(dstIP);
        final String tableId = "IngressPipeImpl.stateful_forward";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("meta.mod_result"), mod_result)
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.ip_to_geo"))
                .withParameter(new PiActionParam(PiActionParamId.of("src_geo"), srcGeo))
                .withParameter(new PiActionParam(PiActionParamId.of("dest_geo"), dstGeo))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .withParameter(new PiActionParam(PiActionParamId.of("spi_addr"), 0))
                .withParameter(new PiActionParam(PiActionParamId.of("first_head_offset"), 14))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_length"), 20))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_offset"), 14))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);
        //log.info("******Build IP Forward table Done********");

        return rule;
    }

    public static FlowRule buildStatefulForward2NdnRule(DeviceId deviceId, String srcIP, String dstIP, byte mod_result, long port) {
        //log.info("******Build IP Forward table ********");
        Long srcNdn = IpToNdn.get(srcIP);
        Long dstNdn = IpToNdn.get(dstIP);
        final String tableId = "IngressPipeImpl.stateful_forward";

        final PiCriterion criterion = PiCriterion.builder()
                .matchExact(PiMatchFieldId.of("meta.mod_result"), mod_result)
                .build();
        final PiAction action = PiAction.builder()
                .withId(PiActionId.of("IngressPipeImpl.ip_to_ndn"))
                .withParameter(new PiActionParam(PiActionParamId.of("src_ndn"), srcNdn))
                .withParameter(new PiActionParam(PiActionParamId.of("dest_ndn"), dstNdn))
                .withParameter(new PiActionParam(PiActionParamId.of("port"), port))
                .withParameter(new PiActionParam(PiActionParamId.of("spi_addr"), 0))
                .withParameter(new PiActionParam(PiActionParamId.of("first_head_offset"), 14))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_length"), 20))
                .withParameter(new PiActionParam(PiActionParamId.of("last_head_offset"), 14))
                .build();

        final FlowRule rule = Utils.buildFlowRule(deviceId, appId, tableId, criterion, action);
        //log.info("******Build IP Forward table Done********");

        return rule;
    }
}
